package com.francis.springbootcommonutil.encry;

import org.apache.commons.codec.binary.Base64;
import org.springframework.util.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * DES对称加密算法  需要密钥和偏移量  速度快
 * 3DES 3重DES， 需要密钥  速度快
 */
public class ThreeDES {

    private static final String THREE_DES_WAY = "DESede";
    private static final String DES_WAY = "DES";
    public static final String DEFAULT_KEY = "2853d046262d8b78a8bc47b1b54dc6a0";    //coeus & md5Hash * 3
    public static final String DEFAULT_IV = "afae1411";     //coeus & md5Hash & substring

    /**
     * 3DESECB加密
     * @param key 8的倍数
     * @param str
     * @return
     */
    public static String encryptThreeDES(String key, String str) {
        if (!StringUtils.isEmpty(key) && !StringUtils.isEmpty(str)) {
            return encryptThreeDES(Md5Hash.desByteCopy(key.getBytes(),24), str.getBytes());
        }
        return null;
    }

    private static String encryptThreeDES(byte[] key, byte[] str) {
        SecretKeySpec keySpec = new SecretKeySpec(key, THREE_DES_WAY);
        try {
            Cipher cipher = Cipher.getInstance(THREE_DES_WAY);
            cipher.init(Cipher.ENCRYPT_MODE, keySpec);
            return Base64.encodeBase64String(cipher.doFinal(str));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 3DESECB解密
     * @param key 8的倍数
     * @param str
     * @return
     */
    public static String decryptThreeDES(String key, String str) {
        if (!StringUtils.isEmpty(key) && !StringUtils.isEmpty(str)) {
            return decryptThreeDES(Md5Hash.desByteCopy(key.getBytes(),24), Base64.decodeBase64(str));
        }
        return null;
    }

    private static String decryptThreeDES(byte[] key, byte[] str) {
        SecretKeySpec keySpec = new SecretKeySpec(key, THREE_DES_WAY);
        try {
            Cipher cipher = Cipher.getInstance(THREE_DES_WAY);
            cipher.init(Cipher.DECRYPT_MODE, keySpec);
            return new String(cipher.doFinal(str));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * DESCBC加密
     * @param iv 8个字节长
     * @param key 8的倍数
     * @param str
     * @return
     */
    public static String encryptDES(String iv, String key, String str) {
        if (!StringUtils.isEmpty(iv) && !StringUtils.isEmpty(key) && !StringUtils.isEmpty(str)) {
            return encryptDES(new IvParameterSpec(iv.getBytes()), Md5Hash.desByteCopy(key.getBytes(), 8),
                    str.getBytes());
        }
        return null;
    }

    private static String encryptDES(IvParameterSpec iv, byte[] key, byte[] str) {
        SecretKeySpec keySpec = new SecretKeySpec(key, DES_WAY);
        try {
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES_WAY);
            SecretKey secretKey = keyFactory.generateSecret(keySpec);
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
            return Base64.encodeBase64String(cipher.doFinal(str));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * DESCBC解密
     * @param iv 8个字节长
     * @param key 8的倍数
     * @param str
     * @return
     */
    public static String decryptDES(String iv, String key, String str) {
        if (!StringUtils.isEmpty(iv) && !StringUtils.isEmpty(key) && !StringUtils.isEmpty(str)) {
            return decryptDES(new IvParameterSpec(iv.getBytes()), Md5Hash.desByteCopy(key.getBytes(),8),
                    Base64.decodeBase64(str));
        }
        return null;
    }

    private static String decryptDES(IvParameterSpec iv, byte[] key, byte[] str) {
        SecretKeySpec keySpec = new SecretKeySpec(key, DES_WAY);
        try {
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES_WAY);
            SecretKey secretKey = keyFactory.generateSecret(keySpec);
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
            return new String(cipher.doFinal(str));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        String data = "hello";
        String thresDES = encryptThreeDES(DEFAULT_KEY, data);
        String decryDES = decryptThreeDES(DEFAULT_KEY, thresDES);
        System.out.println("3DES加密后: " + thresDES);
        System.out.println("3DES解密后: " + decryDES);

        String des = encryptDES(DEFAULT_IV, DEFAULT_KEY, data);
        String enc = decryptDES(DEFAULT_IV, DEFAULT_KEY, des);
        System.out.println("DES加密后: " + des);
        System.out.println("DES解密后: " + enc);

    }

}
